﻿using System;
using System.Collections.Generic;
using TCKQKL.Service.DataContract;
using TCKQKL.FrontEnd.DataModel;
using TCKQKL.Service.LookupClient.LookupSericeReference;
using System.ServiceModel;

namespace TCKQKL.Service.LookupClient
{
    public class LSClient : IDisposable
    {
        LookupServiceClient Lclient;
        public LSClient()
        {
            if (Lclient == null)
            {
                Lclient = new LookupServiceClient();
            }

            Lclient.ClientCredentials.UserName.UserName = "administrator";
            Lclient.ClientCredentials.UserName.Password = "Hn2007";

        }

        public void Close()
        {
            if (Lclient.State == System.ServiceModel.CommunicationState.Faulted)
                Lclient.Abort();
            else
                Lclient.Close();
        }
        public void PrintMessage(string message)
        {
            Lclient.PrintMessage(message);

        }
        public DateTime getTradingDate()
        {
            try
            {
                return Lclient.getTradingDate();
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrders(decimal investorID)
        {
            try
            {

                OrdersBoscModel[] orderModel = Lclient.getOrders(investorID);
                if (orderModel == null)
                    return null;
                List<OrdersBoscDataUI> orderUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orderModel)
                {
                    orderUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return orderUI;
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrdersWaiting(decimal investorID)
        {
            try
            {

                OrdersBoscModel[] orderModel = Lclient.getOrdersWaiting(investorID);
                if (orderModel == null)
                    return null;
                List<OrdersBoscDataUI> orderUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orderModel)
                {
                    orderUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return orderUI;
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrdersHistoryDetail(decimal investorID, DateTime fromDate, DateTime toDate, string orderType, string orderClass, string orderSide, string symbol, string ID, decimal priceLow, decimal priceHigh, decimal qttyLow, decimal qttyHigh)
        {
            try
            {

                OrdersBoscModel[] orderModel = Lclient.getOrdersHistoryDetail(investorID, fromDate, toDate, orderType, orderClass, orderSide, symbol, ID, priceLow, priceHigh, qttyLow, qttyHigh);
                if (orderModel == null)
                    return null;
                List<OrdersBoscDataUI> orderUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orderModel)
                {
                    orderUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return orderUI;
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrdersTopN(decimal investorID, int topN)
        {
            try
            {

                OrdersBoscModel[] orderModel = Lclient.getOrdersTopN(investorID, topN);
                if (orderModel == null)
                    return null;
                List<OrdersBoscDataUI> orderUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orderModel)
                {
                    orderUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return orderUI;
            }
            catch
            {
                throw;
            }
        }
        public List<AccountDataUI> getAccountByInvestorId(decimal investorID)
        {
            try
            {
                AccountDataModel[] accounts = Lclient.getAccountByInvestorID(investorID);
                if (accounts == null)
                    return null;
                List<AccountDataUI> accountUI = new List<AccountDataUI>();
                foreach (AccountDataModel account in accounts)
                {
                    if ((account.tradingAmount > 0) || (account.nettingAmount > 0))
                        accountUI.Add(new AccountDataUI(account.stockId, account.stockName, account.tradingAmount, account.trustedAmount, account.nettingAmount, account.lockedAmount, account.lastModified));
                }

                return accountUI;
            }
            catch
            {
                throw;
            }
        }
        public List<BankDataUI> getBankDataByInvestorId(decimal investorID)
        {
            try
            {
                BankDataModel[] banks = Lclient.getBankByInvestorID(investorID);
                if (banks == null)
                    return null;
                List<BankDataUI> bankUIs = new List<BankDataUI>();
                foreach (BankDataModel bankModel in banks)
                {
                    decimal remainStart = getRemain(investorID, getTradingDate());
                    decimal blockAmount = getBankDataByDate(investorID, DateTime.Now.Date).blockAmount;
                    decimal tradingAmount = remainStart;
                    foreach (TransDataUI tran in getTransByInvestorID(investorID, getTradingDate(), getTradingDate()))
                    {
                        if (tran.IncreaseAmount > 0)
                        {
                            tradingAmount += tran.IncreaseAmount;
                        }
                        else
                            if (tran.DecreaseAmount > 0)
                            {
                                tradingAmount -= tran.DecreaseAmount;
                            }

                    }
                    bankUIs.Add(new BankDataUI(bankModel.bankAccount, bankModel.bankName, tradingAmount - blockAmount, bankModel.trustedAmount, bankModel.nettingAmount, blockAmount, bankModel.openDate, bankModel.lastModified));
                }

                return bankUIs;
            }
            catch
            {
                throw;
            }
        }
        public BankDataUI getBankDataByDate(decimal investorID, DateTime selected)
        {
            try
            {
                BankDataModel bank = Lclient.getBankDataByDate(investorID, selected);
                if (bank == null)
                    return null;
                return new BankDataUI(bank.bankAccount, bank.bankName, bank.tradingAmount, bank.trustedAmount, bank.nettingAmount, bank.blockAmount, bank.openDate, bank.lastModified);
            }
            catch
            {
                throw;
            }

        }

        public List<MatchResultUI> getMatchedResult(decimal investorID)
        {
            try
            {

                MatchedResultModel[] matchs = Lclient.getMatchedResult(investorID);
                if (matchs == null)
                    return null;
                List<MatchResultUI> results = new List<MatchResultUI>();
                foreach (MatchedResultModel result in matchs)
                {
                    results.Add(new MatchResultUI(result.confirmNo, result.stockCode, result.stockQtty, result.price, result.feeAmount, result.orderID, result.transDate, result.TransType));
                }

                return results;
            }
            catch
            {
                throw;
            }
        }
        public List<MatchResultUI> getMatchedResultTopN(decimal investorID, int topN)
        {
            try
            {

                MatchedResultModel[] matchs = Lclient.getMatchedResultTopN(investorID, topN);
                if (matchs == null)
                    return null;
                List<MatchResultUI> results = new List<MatchResultUI>();
                foreach (MatchedResultModel result in matchs)
                {
                    results.Add(new MatchResultUI(result.confirmNo, result.stockCode, result.stockQtty, result.price, result.feeAmount, result.orderID, result.transDate, result.TransType));
                }

                return results;
            }
            catch
            {
                throw;
            }
        }
        public List<MatchResultUI> getMatchedResultEarlyByAccountNo(string accountNo)
        {
            try
            {

                MatchedResultModel[] matchs = Lclient.getMatchedResultEarlyByAccountNo(accountNo);
                if (matchs == null)
                    return null;
                List<MatchResultUI> results = new List<MatchResultUI>();
                foreach (MatchedResultModel result in matchs)
                {
                    results.Add(new MatchResultUI(result.confirmNo, result.stockCode, result.stockQtty, result.price, result.feeAmount, result.orderID, result.transDate, result.TransType));
                }

                return results;
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrdersHistory(decimal investorID, DateTime start, DateTime end)
        {
            try
            {

                OrdersBoscModel[] orders = Lclient.getOrdersHistory(investorID, start, end);
                if (orders == null)
                    return null;
                List<OrdersBoscDataUI> ordersUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orders)
                {
                    ordersUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return ordersUI;
            }
            catch
            {
                throw;
            }
        }
        public List<OrdersBoscDataUI> getOrdersRelatedHistoryByOrderId(string originalOrderID)
        {
            try
            {
                OrdersBoscModel[] orders = Lclient.getOrdersRelatedHistoryByOrderId(originalOrderID);
                if (orders == null)
                    return null;
                List<OrdersBoscDataUI> ordersUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orders)
                {
                    ordersUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return ordersUI;
            }
            catch
            {
                throw;
            }
        }
        public List<TransDataUI> getTransByInvestorID(decimal investorID, DateTime fromDate, DateTime toDate)
        {
            try
            {
                TransDataModel[] trans = Lclient.getTransByInvestorId(investorID, fromDate, toDate);
                if (trans == null)
                    return null;
                decimal remain = getRemain(investorID, fromDate);
                List<TransDataUI> transUI = new List<TransDataUI>();
                foreach (TransDataModel tran in trans)
                {
                    if (tran.IncreaseAmount > 0)
                    {
                        remain += tran.IncreaseAmount;
                        transUI.Add(new TransDataUI(tran.Id, tran.Date, tran.TransText, tran.Code, tran.IncreaseQtty, tran.IncreaseAmount, tran.DecreaseQtty, tran.DecreaseAmount, remain, tran.Note));
                    }
                    else
                        if (tran.DecreaseAmount > 0)
                        {
                            remain -= tran.DecreaseAmount;
                            transUI.Add(new TransDataUI(tran.Id, tran.Date, tran.TransText, tran.Code, tran.IncreaseQtty, tran.IncreaseAmount, tran.DecreaseQtty, tran.DecreaseAmount, remain, tran.Note));
                        }
                        else
                            transUI.Add(new TransDataUI(tran.Id, tran.Date, tran.TransText, tran.Code, tran.IncreaseQtty, tran.IncreaseAmount, tran.DecreaseQtty, tran.DecreaseAmount, remain, tran.Note));

                }
                return transUI;
            }
            catch
            {
                throw;
            }
        }
        public decimal getRemain(decimal investorID, DateTime fromDate)
        {
            try
            {
                return Lclient.getRemain(investorID, fromDate);
            }
            catch
            {
                throw;
            }
        }
        public decimal getNettingAmountByInvestorId(decimal investorID)
        {
            try
            {
                return Lclient.getNettingAmountByInvestorId(investorID);
            }
            catch
            {
                throw;
            }

        }

        public List<OrdersBoscDataUI> getOrdersRelatedByOrderId(string originOrderID)
        {
            try
            {

                OrdersBoscModel[] orders = Lclient.getOrdersRelatedByOrderId(originOrderID);
                if (orders == null)
                    return null;
                List<OrdersBoscDataUI> ordersUI = new List<OrdersBoscDataUI>();
                foreach (OrdersBoscModel order in orders)
                {
                    ordersUI.Add(new OrdersBoscDataUI(order.orderID, order.orderSide, order.orderType, order.orderClass, order.orderStatus, order.openDate, order.symbol, order.quantity, order.price, order.orderFee, order.orderOrigin));
                }

                return ordersUI;
            }
            catch
            {
                throw;
            }

        }
        public List<MatchResultUI> getMatchedResultByOrderID(string orderID)
        {
            try
            {

                MatchedResultModel[] matchs = Lclient.getMatchedResultByOrderID(orderID);
                if (matchs == null)
                    return null;
                List<MatchResultUI> results = new List<MatchResultUI>();
                foreach (MatchedResultModel result in matchs)
                {
                    results.Add(new MatchResultUI(result.confirmNo, result.stockCode, result.stockQtty, result.price, result.feeAmount, result.orderID, result.transDate, result.TransType));
                }

                return results;
            }
            catch
            {
                throw;
            }

        }
        public List<MatchResultUI> getMatchedResultByInvestor(decimal investorID)
        {
            try
            {

                MatchedResultModel[] matchs = Lclient.getMatchedResultByInvestorId(investorID);
                if (matchs == null)
                    return null;
                List<MatchResultUI> results = new List<MatchResultUI>();
                foreach (MatchedResultModel result in matchs)
                {
                    results.Add(new MatchResultUI(result.confirmNo, result.stockCode, result.stockQtty, result.price, result.feeAmount, result.orderID, result.transDate, result.TransType));
                }

                return results;
            }
            catch
            {
                throw;
            }

        }
        public List<OrdersBoscDataUI> getOrderCompleted(decimal investorID)
        {
            return null;
        }
        public InvestorDataUI getAccountData(string accountNo)
        {
            try
            {
                InvestorDataModel investor = Lclient.getAccountData(accountNo);
                if (investor == null)
                    return null;

                return new InvestorDataUI(investor.investorId, investor.accountNo, investor.investorId.ToString());
            }
            catch
            {
                throw;
            }
        }
        public List<InvestorDataUI> getAssignAccountsByInvestorId(decimal investorID)
        {
            List<InvestorDataUI> investors = new List<InvestorDataUI>();
            try
            {
                InvestorDataModel[] members = Lclient.getAssignInvestorData(investorID);
                if (investors == null)
                    return null;
                foreach (InvestorDataModel member in members)
                {
                    InvestorDataUI investor = new InvestorDataUI(member.investorId, member.accountNo, member.investorId.ToString());
                    investors.Add(investor);
                }
                return investors;
            }
            catch
            {
                throw;
            }

        }
        public InvestorDataProfileUI getAccountProfileData(decimal investorID)
        {
            try
            {
                InvestorDataProfileModel investor = Lclient.getAccountProfileData(investorID);
                if (investor == null)
                    return null;

                return new InvestorDataProfileUI(investor.accountNo, investor.name, investor.address, investor.birthday, investor.address, investor.phone, investor.ServiceRegisterd);
            }
            catch
            {
                throw;
            }
        }
        public InvestorDataUI loginProcess(string accountNo, string password)
        {
            try
            {
                InvestorDataModel investor = Lclient.loginProcess(accountNo, password);
                if (investor == null)
                    return null;

                return new InvestorDataUI(investor.investorId, investor.accountNo, investor.bankAccount);
            }
            catch
            {
                throw;
            }
        }
        public void logout(string accountNo)
        {
            try
            {

                Lclient.logout(accountNo);

            }
            catch
            {
                throw;
            }

        }
        public QuoteDataUI getQuote(string symbol)
        {
            try
            {

                StocksDataModel myquote = Lclient.getQuote(symbol);
                if (myquote == null)
                    return new QuoteDataUI(symbol, symbol,1,1,1,1,1,1,1,1,1, "UNDEFINED");

                return new QuoteDataUI(myquote.Symbol, myquote.CompanyName, myquote.Closed, myquote.Open, myquote.Low, myquote.High, myquote.Changed, myquote.Volume, myquote.Ceiling, myquote.Floor, myquote.Ref, myquote.exCenter);
            }
            catch
            {
                throw;
            }
        }
        public MarketSummaryDataUI getMaretSummary(string marketName)
        {
            try
            {

                MarketSummaryDataModel market = Lclient.getMarketSummary(marketName);
                if (market == null)
                    return null;

                return new MarketSummaryDataUI(market.marketName, market.index, market.Changed, market.totalTrade, market.totalShare, market.totalValue, null, null, null, null, null, null, market.summaryDate, market.MarketStatus);
            }
            catch
            {
                throw;
            }
        }

        public List<TradingResultUI> getTradingResult(decimal investorID)
        {
            List<TradingResultUI> results = new List<TradingResultUI>();
            List<OrdersBoscDataUI> orders = new List<OrdersBoscDataUI>();
            try
            {
                orders = getOrdersWaiting(investorID);
                if (orders == null)
                    return null;
                foreach (OrdersBoscDataUI order in orders)
                {
                    TradingResultUI result = new TradingResultUI();
                    result.RootOrder = order;
                    result.RelatedOrders = getOrdersRelatedByOrderId(order.orderID);
                    result.DetailMatched = getMatchedResultByOrderID(order.orderID);
                    result.Symbol = order.symbol;
                    result.Side = order.OrderSide;
                    foreach (MatchResultUI match in result.DetailMatched)
                    {
                        result.SubQtty += match.stockQtty;
                        result.FeeAmount += match.feeAmount;
                        result.SubValue += match.price * match.stockQtty;
                    }
                    if (order.OrderSide.Equals("Mua"))
                        result.SubValue = result.SubValue + result.FeeAmount;
                    else
                        result.SubValue = result.SubValue - result.FeeAmount;
                    if (result.SubQtty > 0)
                        results.Add(result);
                }
                return results;
            }
            catch
            {
                throw;
            }
        }
        public List<TradingResultUI> getTradingResultHistory(decimal investorID, DateTime fromDate, DateTime toDate, string orderType, string orderClass, string orderSide, string symbol, string ID, decimal priceLow, decimal priceHigh, decimal qttyLow, decimal qttyHigh)
        {
            List<TradingResultUI> results = new List<TradingResultUI>();
            List<OrdersBoscDataUI> orders = new List<OrdersBoscDataUI>();
            try
            {
                orders = getOrdersHistoryDetail(investorID, fromDate, toDate, orderType, orderClass, orderSide, symbol, ID, priceLow, priceHigh, qttyLow, qttyHigh);
                if (orders == null)
                    return null;
                foreach (OrdersBoscDataUI order in orders)
                {
                    TradingResultUI result = new TradingResultUI();
                    result.RootOrder = order;
                    result.RelatedOrders = getOrdersRelatedHistoryByOrderId(order.orderID);
                    result.DetailMatched = getMatchedResultByOrderID(order.orderID);
                    result.Symbol = order.symbol;
                    result.Side = order.OrderSide;
                    foreach (MatchResultUI match in result.DetailMatched)
                    {
                        result.SubQtty += match.stockQtty;
                        result.FeeAmount += match.feeAmount;
                        result.SubValue += match.price * match.stockQtty;
                    }
                    if (order.OrderSide.Equals("Mua"))
                        result.SubValue = result.SubValue + result.FeeAmount;
                    else
                        result.SubValue = result.SubValue - result.FeeAmount;

                    switch (orderType)
                    {
                        case "MATCHED":
                            if (result.SubQtty > 0)
                                results.Add(result);
                            break;
                        default:
                            results.Add(result);
                            break;
                    }
                }
                return results;
            }
            catch
            {
                throw;
            }
        }

        public List<HoldingDataUI> getHolding(decimal investorID)
        {
            List<HoldingDataUI> holdings = new List<HoldingDataUI>();
            List<AccountDataUI> accounts = new List<AccountDataUI>();
            try
            {
                accounts = getAccountByInvestorId(investorID);
                if (accounts == null)
                    return null;
                List<MatchResultUI> results = getMatchedResultByInvestor(investorID);

                foreach (AccountDataUI account in accounts)
                {
                    HoldingDataUI holding = new HoldingDataUI();
                    holding.Account = account;
                    holding.Quotes = getQuote(account.stockId);

                    holding.tradingResult = new List<MatchResultUI>();
                    // = getMatchedResultByInvestorAndStockCode(investorID, account.stockId);

                    decimal quantity = 0;
                    foreach (MatchResultUI match in results)
                    {
                        if (match.stockCode.Equals(account.stockId))
                        {
                            holding.tradingResult.Add(match);

                            if (match.TransType.Trim().Equals("Mua"))
                            {
                                quantity += match.stockQtty;
                                if (quantity > 0)
                                {
                                    holding.TotalValue += match.price * match.stockQtty;
                                    holding.AverageBought = holding.TotalValue / quantity;
                                }
                                else
                                {
                                    holding.TotalValue = match.price * match.stockQtty;
                                    holding.AverageBought = match.price;
                                }

                            }
                            else
                            {
                                quantity -= match.stockQtty;
                                if (quantity < 0)
                                {
                                    holding.TotalValue -= match.price * match.stockQtty;
                                    holding.Gain += 0 - match.stockQtty * (match.price - holding.AverageBought);
                                }
                                else if (quantity > 0)
                                {
                                    holding.TotalValue -= holding.AverageBought * match.stockQtty;
                                    holding.Gain += match.stockQtty * (match.price - holding.AverageBought);
                                }
                                else
                                {
                                    holding.TotalValue = 0;
                                    holding.AverageBought = 0;
                                }
                            }
                        }
                    }
                    if (holding.Quotes != null)
                        holdings.Add(holding);
                }
                return holdings;
            }
            catch
            {
                throw;
            }
        }
        public TotalHoldingDataUI getTotalHolding(decimal investorID)
        {
            List<HoldingDataUI> holdingList = getHolding(investorID);
            if (holdingList == null)
                return null;
            TotalHoldingDataUI totalHolding = new TotalHoldingDataUI();
            try
            {
                totalHolding.Holding = holdingList;
                totalHolding.AccountProfile = getAccountProfileData(investorID);
                //totalHolding.BankData = getBankDataByInvestorId(investorID);
                foreach (HoldingDataUI holding in holdingList)
                {
                    totalHolding.TradingValue += holding.Account.tradingAmount * holding.Quotes.Closed * 1000;
                    totalHolding.NettingValue += holding.Account.nettingAmount * holding.Quotes.Closed * 1000;
                    totalHolding.LockedValue += holding.Account.lockedAmount * holding.Quotes.Closed * 1000;
                    totalHolding.TotalGain += holding.Gain;
                }
                totalHolding.TotalValue = (totalHolding.TradingValue + totalHolding.NettingValue) * 1000;
                return totalHolding;
            }
            catch
            {
                throw;
            }
        }
        public PersonalHoldingUI getPersonalHolding(decimal investorID)
        {
            PersonalHoldingUI personal = new PersonalHoldingUI();
            try
            {
                personal.MainAccount = getTotalHolding(investorID);
                if (personal.MainAccount == null)
                    return null;
                personal.TradingValue += personal.MainAccount.TradingValue;
                personal.NettingValue += personal.MainAccount.NettingValue;
                personal.LockedValue += personal.MainAccount.LockedValue;
                personal.TotalValue += personal.MainAccount.TotalValue;
                personal.TotalGain += personal.MainAccount.TotalGain;

                List<InvestorDataUI> assignInvestors = getAssignAccountsByInvestorId(investorID);
                personal.AssignAccounts = new List<TotalHoldingDataUI>();
                foreach (InvestorDataUI investor in assignInvestors)
                {
                    TotalHoldingDataUI totalHolding = new TotalHoldingDataUI();
                    totalHolding = getTotalHolding(investor.investorId);
                    personal.AssignAccounts.Add(totalHolding);

                    personal.TradingValue += totalHolding.TradingValue;
                    personal.NettingValue += totalHolding.NettingValue;
                    personal.LockedValue += totalHolding.LockedValue;
                    personal.TotalValue += totalHolding.TotalValue;
                    personal.TotalGain += totalHolding.TotalGain;
                }
                return personal;
            }
            catch
            {
                throw;
            }
        }
        public TotalTradingResultUI getTotalTradingResult(decimal investorID)
        {
            TotalTradingResultUI totalResult = new TotalTradingResultUI();
            try
            {
                totalResult.InvestorProfile = getAccountProfileData(investorID);
                totalResult.TradingResults = getTradingResult(investorID);
                foreach (TradingResultUI result in totalResult.TradingResults)
                {
                    totalResult.TotalValue += result.SubValue;
                    totalResult.TotalFee += result.FeeAmount;
                }
                return totalResult;
            }
            catch
            {
                throw;
            }
        }
        public TotalTradingResultUI getTotalTradingResultHistory(decimal investorID, DateTime fromDate, DateTime toDate, string orderType, string orderClass, string orderSide, string symbol, string ID, decimal priceLow, decimal priceHigh, decimal qttyLow, decimal qttyHigh)
        {
            TotalTradingResultUI totalResult = new TotalTradingResultUI();
            try
            {
                totalResult.InvestorProfile = getAccountProfileData(investorID);
                totalResult.TradingResults = getTradingResultHistory(investorID, fromDate, toDate, orderType, orderClass, orderSide, symbol, ID, priceLow, priceHigh, qttyLow, qttyHigh);
                foreach (TradingResultUI result in totalResult.TradingResults)
                {
                    totalResult.TotalValue += result.SubValue;
                    totalResult.TotalFee += result.FeeAmount;
                }
                return totalResult;
            }
            catch
            {
                throw;
            }
        }
        public PersonalTradingResultUI getPersonalTradingResult(decimal investorID, bool assignAccount)
        {
            PersonalTradingResultUI personal = new PersonalTradingResultUI();
            try
            {
                personal.MainTradingResult = getTotalTradingResult(investorID);
                personal.TotalValue += personal.MainTradingResult.TotalValue;
                personal.TotalFee += personal.MainTradingResult.TotalFee;

                List<InvestorDataUI> assignInvestors = getAssignAccountsByInvestorId(investorID);
                personal.AssignTradingResult = new List<TotalTradingResultUI>();
                foreach (InvestorDataUI investor in assignInvestors)
                {
                    TotalTradingResultUI tradingResult = new TotalTradingResultUI();
                    if (assignAccount)
                    {
                        tradingResult = getTotalTradingResult(investor.investorId);
                        personal.AssignTradingResult.Add(tradingResult);

                        personal.TotalValue += tradingResult.TotalValue;
                        personal.TotalFee += tradingResult.TotalFee;
                    }
                }
                return personal;
            }
            catch
            {
                throw;
            }
        }
        public PersonalTradingResultUI getPersonalTradingResultHistory(decimal investorID, DateTime fromDate, DateTime toDate, string orderType, string orderClass, string orderSide, string symbol, string ID, decimal priceLow, decimal priceHigh, decimal qttyLow, decimal qttyHigh, bool assignAccount)
        {
            PersonalTradingResultUI personal = new PersonalTradingResultUI();
            try
            {
                personal.MainTradingResult = getTotalTradingResultHistory(investorID, fromDate, toDate, orderType, orderClass, orderSide, symbol, ID, priceLow, priceHigh, qttyLow, qttyHigh);
                personal.TotalValue += personal.MainTradingResult.TotalValue;
                personal.TotalFee += personal.MainTradingResult.TotalFee;

                if (assignAccount)
                {
                    List<InvestorDataUI> assignInvestors = getAssignAccountsByInvestorId(investorID);
                    personal.AssignTradingResult = new List<TotalTradingResultUI>();
                    foreach (InvestorDataUI investor in assignInvestors)
                    {
                        TotalTradingResultUI tradingResult = new TotalTradingResultUI();
                        tradingResult = getTotalTradingResultHistory(investor.investorId, fromDate, toDate, orderType, orderClass, orderSide, symbol, ID, priceLow, priceHigh, qttyLow, qttyHigh);
                        personal.AssignTradingResult.Add(tradingResult);

                        personal.TotalValue += tradingResult.TotalValue;
                        personal.TotalFee += tradingResult.TotalFee;
                    }
                }
                else
                {
                    personal.AssignTradingResult = null;
                }
                return personal;
            }
            catch
            {
                throw;
            }
        }

        public int PlaceOrder(OrdersOnlineUI order)
        {
            try
            {

                int preCheck = PremierOrderCheck(order);

                if (preCheck > 0)
                    return preCheck;

                int serviceResult = Lclient.PlaceOrder(new OrdersOnlineModel(0, order.OrderId, order.AccountNo, order.OrderSide, order.Symbol, order.OrderSpec, order.OrderClass, order.OrderMode, order.OpenDate, order.ExpireDate, order.OrderNo, order.TimeStamp, order.Price, order.Quantity, order.OrderType));

                if (serviceResult != 50)
                    return serviceResult;
                else
                    return 0;
            }
            catch
            {
                throw;
            }

        }

        public int ChangeOrder(OrdersOnlineUI original, OrdersOnlineUI changed)
        {
            try
            {
                int preCheck = PremierOrderCheck(changed);

                if (preCheck > 0)
                    return preCheck;

                int result = Lclient.ChangeOrder(new OrdersOnlineModel(0, original.OrderId, original.AccountNo, original.OrderSide, original.Symbol, original.OrderSpec, original.OrderClass, original.OrderMode, original.OpenDate, original.ExpireDate, original.OrderNo, original.TimeStamp, original.Price, original.Quantity, original.OrderType),
                                    new OrdersOnlineModel(0, changed.OrderId, changed.AccountNo, changed.OrderSide, changed.Symbol, changed.OrderSpec, changed.OrderClass, changed.OrderMode, changed.OpenDate, changed.ExpireDate, changed.OrderNo, changed.TimeStamp, changed.Price, changed.Quantity, changed.OrderType));
                if (result != 50)
                    return result;
                else
                    return 0;

            }
            catch
            {
                throw;
            }
        }

        public int CancelOrder(OrdersOnlineUI original)
        {
            try
            {
                int result = Lclient.CancelOrder(new OrdersOnlineModel(0, original.OrderId, original.AccountNo, original.OrderSide, original.Symbol, original.OrderSpec, original.OrderClass, original.OrderMode, original.OpenDate, original.ExpireDate, original.OrderNo, original.TimeStamp, original.Price, original.Quantity, original.OrderType));
                if (result != 50)
                    return result;
                else
                    return 0;

            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
        private int getPhaseByHour(DateTime stamp)
        {
            if (stamp.Hour.Equals(8) && stamp.Minute < 50)
                return 1;
            else
                if (stamp.Hour.Equals(9) || (stamp.Hour.Equals(10) && stamp.Minute < 8))
                    return 2;
                else
                    if (stamp.Hour.Equals(10) && stamp.Minute < 20)
                        return 3;
            return 0;
        }

        private int PremierOrderCheck(OrdersOnlineUI order)
        {
            StocksInfoUI stk = GetStockInfo(order.Symbol.ToUpper());
            decimal OrderPrice = 0;

            //Symbol does not exist
            if (string.IsNullOrEmpty(order.OrderClass))
                return 11;

            //Check price range
            if (order.OrderClass == "LO")
            {
                try
                {
                    string normPrice = "";
                    if (order.Price.IndexOf('.') > 0)
                        normPrice = order.Price.Trim().Substring(0, order.Price.IndexOf('.') + 1);
                    OrderPrice = Convert.ToDecimal(order.Price);
                }
                catch
                {
                    return 1;
                }

                if (OrderPrice > stk.Ceiling)
                    return 2;
                else
                    if (OrderPrice < stk.Floor)
                        return 3;


                //Check price and quantity detail
                if (stk.exCenter.Equals("HOSE"))
                {
                    if ((OrderPrice >= 50) && (OrderPrice < 100) && ((OrderPrice * 10) % 5 != 0))
                        return 4;
                    if ((OrderPrice >= 100) && (OrderPrice * 10 % 10 != 0))
                        return 5;
                    if (order.Quantity > 20000)
                        return 6;
                    if (order.Quantity % 10 != 0)
                        return 7;
                }
                else
                    if (stk.exCenter.Equals("HASTC"))
                    {
                        if (order.Quantity % 100 != 0)
                            return 8;
                        if (order.Quantity > 20000)
                            return 9;
                    }
            }
            else
            {
                //Hastc does not have ato/atc
                if (stk.exCenter.Equals("HASTC"))
                    return 10;
                else
                    if (stk.exCenter.Equals("HOSE"))
                    {
                        //Check time

                    }
            }
            return 0;
        }

        //from Bosc
        public StocksInfoUI GetStockInfo(string symbol)
        {
            try
            {
                StocksDataModel stk = Lclient.GetStockInfo(symbol);
                if (stk != null)
                    return new StocksInfoUI(stk.Symbol, stk.CompanyName, stk.Closed, stk.Open, stk.Low, stk.High, stk.Changed, stk.Volume, stk.Ceiling, stk.Floor, stk.Ref, stk.exCenter);
                else
                    return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        //from stock board
        public StocksInfoUI GetStockDetail(string symbol)
        {
            try
            {
                StocksDataModel myquote = Lclient.getQuote(symbol);
                if (myquote == null)
                    return null;

                return new StocksInfoUI(myquote.Symbol, myquote.CompanyName, myquote.Closed, myquote.Open, myquote.Low, myquote.High, myquote.Changed, myquote.Volume, myquote.Ceiling, myquote.Floor, myquote.Ref, myquote.exCenter);
            }
            catch
            {
                throw;
            }

        }

        public List<OrdersOnlineUI> getOrderListByStatus(string status)
        {
            try
            {
                List<OrdersOnlineUI> newList = new List<OrdersOnlineUI>();
                OrdersOnlineModel[] list = Lclient.getOrderListByStatus(status);
                if (list == null)
                    return null;
                foreach (OrdersOnlineModel item in list)
                    newList.Add(new OrdersOnlineUI(item.OrderLineNum, item.AccountNo, item.OrderSide, item.Symbol, item.OrderSpec, item.OrderClass, item.OrderMode, item.OpenDate, item.ExpireDate, item.OrderNo, item.TimeStamp, item.Price, item.Quantity, item.OrderType));
                return newList;

            }
            catch
            {
                throw;
            }
        }

        public List<OrdersOnlineUI> getOrderListByStatusAndAccountNo(string status, string AccountNo)
        {
            try
            {
                List<OrdersOnlineUI> newList = new List<OrdersOnlineUI>();
                OrdersOnlineModel[] list = Lclient.getOrderListByStatusAndAccountNo(status, AccountNo);
                if (list == null)
                    return null;
                foreach (OrdersOnlineModel item in list)
                    newList.Add(new OrdersOnlineUI(item.OrderLineNum, item.AccountNo, item.OrderSide, item.Symbol, item.OrderSpec, item.OrderClass, item.OrderMode, item.OpenDate, item.ExpireDate, item.OrderNo, item.TimeStamp, item.Price, item.Quantity, item.OrderType));
                return newList;

            }
            catch
            {
                throw;
            }
        }

        public OrdersOnlineUI getNewestOrder(string OrgStatus, string StatusAfter)
        {
            try
            {
                OrdersOnlineModel item = Lclient.getNewestOrder(OrgStatus, StatusAfter);
                if (item == null)
                    return null;
                return new OrdersOnlineUI(item.OrderLineNum, item.AccountNo, item.OrderSide, item.Symbol, item.OrderSpec, item.OrderClass, item.OrderMode, item.OpenDate, item.ExpireDate, item.OrderNo, item.TimeStamp, item.Price, item.Quantity, item.OrderType);

            }
            catch
            {
                throw;
            }

        }

        public OrdersOnlineUI GetOrderByOrderId(int OrderId)
        {
            try
            {
                OrdersOnlineModel item = Lclient.GetOrderByOrderId(OrderId);
                if (item == null)
                    return null;
                return new OrdersOnlineUI(item.OrderLineNum, item.AccountNo, item.OrderSide, item.Symbol, item.OrderSpec, item.OrderClass, item.OrderMode, item.OpenDate, item.ExpireDate, item.OrderNo, item.TimeStamp, item.Price, item.Quantity, item.OrderType);

            }
            catch
            {
                throw;
            }
        }

        public OrdersOnlineUI getOrderOriginal(int OrderId)
        {
            try
            {
                OrdersOnlineModel item = Lclient.getOrderOriginal(OrderId);
                if (item == null)
                    return null;
                return new OrdersOnlineUI(item.OrderLineNum, item.AccountNo, item.OrderSide, item.Symbol, item.OrderSpec, item.OrderClass, item.OrderMode, item.OpenDate, item.ExpireDate, item.OrderNo, item.TimeStamp, item.Price, item.Quantity, item.OrderType);

            }
            catch
            {
                throw;
            }
        }

        public int UpdateOrderStatus(int OrderPlaceId, string Status)
        {
            try
            {
                return Lclient.UpdateOrderStatus(OrderPlaceId, Status);

            }
            catch
            {
                throw;
            }
        }

        public decimal getPeddingOrderCost()
        {
            decimal cost = 0;
            List<OrdersOnlineUI> orderList = getOrderListByStatus("");
            if (orderList != null)
            {
                foreach (OrdersOnlineUI item in orderList)
                {
                    if (item.OrderSide.Equals("BUY"))
                    {
                        if (item.OrderType.Equals("PLACE"))
                            cost += item.Quantity * (item.OrderClass.Equals("LO") ? Convert.ToDecimal(item.Price) : GetStockInfo(item.Symbol).Ceiling) * 1000;
                        else
                            if (item.OrderType.Equals("CHANGE"))
                            {
                                StocksInfoUI stk = GetStockInfo(item.Symbol);
                                cost += item.Quantity * (stk.Ceiling - stk.Floor) * 1000;
                            }
                    }
                }
            }
            return cost;
        }

        public decimal getLockedQuantity(string symbol)
        {
            decimal locked = 0;
            List<OrdersOnlineUI> orderList = getOrderListByStatus("");
            if (orderList != null)
            {
                foreach (OrdersOnlineUI item in orderList)
                    if (item.OrderSide.Equals("SELL") && item.OrderType.Equals("PLACE") && item.Symbol.Equals(symbol))
                        locked += item.Quantity;
            }
            return locked;
        }

        public List<DateTime> getBackDate()
        {
            try
            {
                List<DateTime> newList = new List<DateTime>();
                DateTime[] list = Lclient.getBackDate();
                if (list == null)
                    return null;
                foreach (DateTime item in list)
                    newList.Add(item);

                return newList;
            }
            catch
            {
                throw;
            }
        }

        public decimal getPreLoanByInvestor(decimal investorid)
        {
            return Lclient.getPreLoanByInvestor(investorid);            
        }

        public List<AccountDataUI> getStockNettingInvestorId(decimal investorID, DateTime transdate)
        {
            try
            {
                List<AccountDataUI> newList = new List<AccountDataUI>();
                AccountDataModel[] list = Lclient.getStockNettingInvestorId(investorID, transdate);
                if (list == null)
                    return null;
                foreach (AccountDataModel item in list)
                    newList.Add(new AccountDataUI(item.stockId,item.stockName, item.tradingAmount,item.trustedAmount, item.nettingAmount, item.lockedAmount,item.openDate));

                return newList;
            }
            catch
            {
                throw;
            }
        }


        #region IDisposable Members

        void IDisposable.Dispose()
        {
            if (Lclient.State == CommunicationState.Faulted)
            {
                Lclient.Abort();
            }
            else
            {
                Lclient.Close();
            }
        }

        #endregion
    }
}
